package com.ciaojian.bytedance.config.aspect;

import com.alibaba.fastjson.JSONObject;
import com.ciaojian.core.util.LogUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author oxiny
 */
@Component
@Aspect
public class ControllerPoint {
    /**
     * 过滤请求头
     */
    private final Set<String> HEADERS_FILTER = Stream.of("pragma", "accept", "cache-control",
            "host", "accept-encoding", "connection", "content-length",
            "user-agent", "postman-token", "upgrade-insecure-requests", "accept-language",
            "charset", "origin", "referer", "sec-fetch-site", "sec-fetch-mode",
            "sec-fetch-user", "sec-fetch-dest", "x-forwarded-for").collect(Collectors.toSet());
    /**
     * 接口执行计时器
     */
    private final Map<String, Date> TIMERS = new HashMap<>();


    @Before(value = "execution(public * com.ciaojian.bytedance.controller.*.*(..))")
    public void businessBefore(JoinPoint joinPoint) throws JsonProcessingException {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();

        // 前端一直在轮询这个接口,这里排除掉这个接口无意义的日志
        if ("http://cj.ciaojian.com/bytedance/order".contentEquals(request.getRequestURL())) {
            return;
        }

        LogUtil.writeBusinessLog("****************************************************************************************************************************************************************************");
        LogUtil.writeBusinessLog("请求接口={}", request.getRequestURL());
        LogUtil.writeBusinessLog("请求方法={}", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, Object> headerMap = new LinkedHashMap<>();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            if (HEADERS_FILTER.contains(name)) {
                continue;
            }
            String value = request.getHeader(name);
            headerMap.put(name, value);
        }
        LogUtil.writeBusinessLog("请求header={}", objectMapper.writeValueAsString(headerMap));

        // 打印参数
        Map<String, Object> map = new LinkedHashMap<>();
        Enumeration<String> pNames = request.getParameterNames();
        while (pNames.hasMoreElements()) {
            String name = pNames.nextElement();
            String value = request.getParameter(name);
            map.put(name, value);
        }
        LogUtil.writeBusinessLog("请求参数={}", "".equals(objectMapper.writeValueAsString(map)) ? "{}" : objectMapper.writeValueAsString(map));
        LogUtil.writeBusinessLog("请求地址={}", request.getRemoteAddr());
        LogUtil.writeBusinessLog("请求方式={}", request.getMethod());
    }

    @AfterReturning(value = "execution(public * com.ciaojian.bytedance.controller.*.*(..))", returning = "value")
    public synchronized void businessAfter(Object value) {
        if (value != null) {
            if (!JSONObject.toJSON(value).toString().contains("data:image/jpeg;base64")) {
                if (JSONObject.toJSON(value).toString().length() < 3000) {
                    LogUtil.writeBusinessLog("响应参数={}", JSONObject.toJSON(value));
                } else {
                    LogUtil.writeBusinessLog("响应参数={}", "内容过大无法显示");
                }
            }
        }
    }
}
